package com.changgou.oauth.service.impl;

import com.changgou.oauth.service.AuthService;
import com.changgou.oauth.util.AuthToken;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.stereotype.Service;
import org.springframework.util.Base64Utils;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.DefaultResponseErrorHandler;
import org.springframework.web.client.RestTemplate;

import java.io.IOException;
import java.net.URI;
import java.util.Base64;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Service
public class AuthServiceImpl implements AuthService {


    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Value("${auth.ttl}")
    private long ttl;

    @Autowired
    private LoadBalancerClient loadBalancerClient;
    @Override
    public AuthToken login(String username, String password, String clientId, String clientSecret) {

        //1.申请令牌

        //在注册中心获取url
        ServiceInstance serviceInstance = loadBalancerClient.choose("user-auth");
        URI uri = serviceInstance.getUri();
        String url = uri+"/oauth/token";


        //body
        MultiValueMap<String, String> body = new LinkedMultiValueMap<>();
        body.add("grant_type","password");
        body.add("username",username);
        body.add("password",password);


        //headers
        MultiValueMap<String, String> headers = new LinkedMultiValueMap<>();
        headers.add("Authorization",this.getHttpBasic(clientId,clientSecret));


        HttpEntity<MultiValueMap<String,String>> requestEntity = new HttpEntity<>(body,headers);


        //400  401 异常放行
        restTemplate.setErrorHandler(new DefaultResponseErrorHandler(){


            @Override
            public void handleError(ClientHttpResponse response) throws IOException {

                if (response.getRawStatusCode()!=400 && response.getRawStatusCode()!=401){
                    super.handleError(response);
                }

            }
        });



        ResponseEntity<Map> responseEntity = restTemplate.exchange(url, HttpMethod.POST, requestEntity, Map.class);

        Map map = responseEntity.getBody();
        if (map == null || map.get("access_token")==null ||map.get("refresh_token")==null  ||map.get("jti")==null){
            //申请令牌失败

            throw new RuntimeException("申请令牌失败");

        }


        //2.封装结果数据

        AuthToken authToken = new AuthToken();

        authToken.setAccessToken((String) map.get("access_token"));

        authToken.setRefreshToken((String) map.get("refresh_token"));

        authToken.setJti((String) map.get("jti"));

        //3.将jti作为redis中的key，将jwt作为redis中的value进行数据的存放

        stringRedisTemplate.boundValueOps(authToken.getJti()).set(authToken.getAccessToken(),ttl, TimeUnit.SECONDS);


        return authToken;



    }

    private String getHttpBasic(String clientId, String clientSecret) {
        String value = clientId+":"+clientSecret;

        byte[] encode = Base64Utils.encode(value.getBytes());

        return "Basic "+new String(encode);

    }
}
